"""
API网关核心服务
==============

基于RedFire框架的统一网关服务
负责请求路由、认证、限流等核心功能
"""

import asyncio
import time
import logging
from typing import Dict, Any, Optional, List
from fastapi import Request, Response, HTTPException
import httpx

from redfire_framework.cache.service import CacheService
from redfire_framework.events.bus import EventBus
from redfire_framework.middleware.manager import MiddlewareManager

logger = logging.getLogger(__name__)


class GatewayService:
    """
    网关核心服务
    
    负责：
    - 请求路由和转发
    - 认证和授权
    - 速率限制
    - 负载均衡
    - 监控和指标
    """
    
    def __init__(
        self,
        cache_service: Optional[CacheService] = None,
        event_bus: Optional[EventBus] = None,
        middleware_manager: Optional[MiddlewareManager] = None,
        config: Optional[Dict[str, Any]] = None
    ):
        """
        初始化网关服务
        
        Args:
            cache_service: 缓存服务
            event_bus: 事件总线
            middleware_manager: 中间件管理器
            config: 配置信息
        """
        self.cache_service = cache_service
        self.event_bus = event_bus
        self.middleware_manager = middleware_manager
        self.config = config or {}
        
        # HTTP客户端
        connect_timeout = self.config.get("performance", {}).get("connection_timeout", 30.0)
        read_timeout = self.config.get("performance", {}).get("read_timeout", 30.0)
        
        self.http_client = httpx.AsyncClient(
            timeout=httpx.Timeout(
                timeout=read_timeout,  # 默认超时
                connect=connect_timeout,
                read=read_timeout,
                write=connect_timeout,
                pool=5.0
            ),
            limits=httpx.Limits(
                max_connections=self.config.get("performance", {}).get("max_connections", 100),
                max_keepalive_connections=self.config.get("performance", {}).get("max_keepalive_connections", 20)
            )
        )
        
        # 路由缓存
        self._route_cache: Dict[str, Any] = {}
        self._service_instances: Dict[str, List[Dict[str, Any]]] = {}
        
        logger.info("Gateway service initialized")
    
    async def handle_request(self, request: Request) -> Response:
        """
        处理网关请求
        
        Args:
            request: FastAPI请求对象
            
        Returns:
            Response: 响应对象
        """
        start_time = time.time()
        request_id = f"req_{int(time.time() * 1000)}"
        
        try:
            # 发布请求开始事件
            if self.event_bus:
                self.event_bus.publish("gateway.request.started", {
                    "request_id": request_id,
                    "method": request.method,
                    "path": request.url.path,
                    "timestamp": start_time
                })
            
            # 查找路由
            route_info = await self._find_route(request.url.path, request.method)
            if not route_info:
                raise HTTPException(status_code=404, detail="Route not found")
            
            # 检查认证
            if route_info.get("auth_required", False):
                await self._check_authentication(request)
            
            # 检查速率限制
            if self.config.get("rate_limiting_enabled", True):
                await self._check_rate_limit(request, route_info)
            
            # 获取目标服务实例
            service_instance = await self._get_service_instance(route_info["service_name"])
            if not service_instance:
                raise HTTPException(status_code=503, detail="Service unavailable")
            
            # 转发请求
            response = await self._forward_request(request, route_info, service_instance)
            
            # 记录成功指标
            duration = time.time() - start_time
            await self._record_metrics(request_id, route_info, duration, True)
            
            # 发布请求完成事件
            if self.event_bus:
                self.event_bus.publish("gateway.request.completed", {
                    "request_id": request_id,
                    "status_code": response.status_code,
                    "duration": duration
                })
            
            return response
            
        except HTTPException:
            # 记录失败指标
            duration = time.time() - start_time
            await self._record_metrics(request_id, route_info if 'route_info' in locals() else None, duration, False)
            raise
        except Exception as e:
            # 记录错误指标
            duration = time.time() - start_time
            await self._record_metrics(request_id, route_info if 'route_info' in locals() else None, duration, False)
            
            logger.error(f"Gateway request handling error: {e}", exc_info=True)
            
            # 发布错误事件
            if self.event_bus:
                self.event_bus.publish("gateway.request.error", {
                    "request_id": request_id,
                    "error": str(e),
                    "duration": duration
                })
            
            raise HTTPException(status_code=500, detail="Internal gateway error")
    
    async def _find_route(self, path: str, method: str) -> Optional[Dict[str, Any]]:
        """
        查找匹配的路由
        
        Args:
            path: 请求路径
            method: HTTP方法
            
        Returns:
            Optional[Dict[str, Any]]: 路由信息
        """
        # 从缓存获取路由
        cache_key = f"route:{path}:{method}"
        
        if self.cache_service:
            cached_route = await self.cache_service.get(cache_key)
            if cached_route:
                return cached_route
        
        # 从配置查找路由
        routes = self.config.get("routes", [])
        for route in routes:
            if self._match_route_path(path, route["path"]) and method.upper() in route.get("methods", ["GET"]):
                route_info = dict(route)
                
                # 缓存路由信息
                if self.cache_service:
                    await self.cache_service.set(cache_key, route_info, ttl=300)  # 5分钟缓存
                
                return route_info
        
        return None
    
    def _match_route_path(self, request_path: str, route_pattern: str) -> bool:
        """
        匹配路由路径
        
        Args:
            request_path: 请求路径
            route_pattern: 路由模式
            
        Returns:
            bool: 是否匹配
        """
        # 简单的通配符匹配
        if route_pattern.endswith("/*"):
            prefix = route_pattern[:-2]
            return request_path.startswith(prefix)
        
        return request_path == route_pattern
    
    async def _check_authentication(self, request: Request):
        """
        检查认证
        
        Args:
            request: 请求对象
        """
        # 简单的JWT认证检查
        auth_header = request.headers.get("Authorization")
        if not auth_header or not auth_header.startswith("Bearer "):
            raise HTTPException(status_code=401, detail="Authentication required")
        
        # 这里应该验证JWT token，暂时简化
        token = auth_header[7:]  # 移除 "Bearer " 前缀
        if not token:
            raise HTTPException(status_code=401, detail="Invalid token")
    
    async def _check_rate_limit(self, request: Request, route_info: Dict[str, Any]):
        """
        检查速率限制
        
        Args:
            request: 请求对象
            route_info: 路由信息
        """
        if not self.cache_service:
            return  # 没有缓存服务，跳过限流
        
        rate_limit = route_info.get("rate_limit", 100)
        if rate_limit <= 0:
            return  # 无限制
        
        # 使用客户端IP作为限流键
        client_ip = request.client.host if request.client else "unknown"
        rate_key = f"rate_limit:{client_ip}:{route_info['path']}"
        
        # 获取当前计数
        current_count = await self.cache_service.get(rate_key) or 0
        
        if current_count >= rate_limit:
            raise HTTPException(status_code=429, detail="Rate limit exceeded")
        
        # 增加计数
        await self.cache_service.set(rate_key, current_count + 1, ttl=60)  # 1分钟窗口
    
    async def _get_service_instance(self, service_name: str) -> Optional[Dict[str, Any]]:
        """
        获取服务实例
        
        Args:
            service_name: 服务名称
            
        Returns:
            Optional[Dict[str, Any]]: 服务实例信息
        """
        # 从配置获取服务实例
        services = self.config.get("services", {})
        instances = services.get(service_name, [])
        
        if not instances:
            return None
        
        # 简单的轮询负载均衡
        # 这里应该实现更复杂的负载均衡算法
        import random
        return random.choice(instances)
    
    async def _forward_request(
        self, 
        request: Request, 
        route_info: Dict[str, Any], 
        service_instance: Dict[str, Any]
    ) -> Response:
        """
        转发请求到目标服务
        
        Args:
            request: 原始请求
            route_info: 路由信息
            service_instance: 目标服务实例
            
        Returns:
            Response: 目标服务响应
        """
        # 构建目标URL
        target_host = service_instance["host"]
        target_port = service_instance["port"]
        target_path = route_info.get("target_path", "")
        
        # 替换路径
        original_path = request.url.path
        if route_info["path"].endswith("/*"):
            # 通配符路由，保留后缀
            prefix = route_info["path"][:-2]
            suffix = original_path[len(prefix):]
            final_path = f"{target_path}{suffix}"
        else:
            final_path = target_path or original_path
        
        target_url = f"http://{target_host}:{target_port}{final_path}"
        
        # 添加查询参数
        if request.url.query:
            target_url += f"?{request.url.query}"
        
        # 准备请求头
        headers = dict(request.headers)
        # 移除可能导致问题的头
        headers.pop("host", None)
        headers.pop("content-length", None)
        
        # 读取请求体
        body = await request.body()
        
        try:
            # 发送请求
            timeout = route_info.get("timeout", 30.0)
            response = await self.http_client.request(
                method=request.method,
                url=target_url,
                headers=headers,
                content=body,
                timeout=timeout
            )
            
            # 构建响应
            return Response(
                content=response.content,
                status_code=response.status_code,
                headers=dict(response.headers),
                media_type=response.headers.get("content-type")
            )
            
        except httpx.TimeoutException:
            raise HTTPException(status_code=504, detail="Gateway timeout")
        except httpx.ConnectError:
            raise HTTPException(status_code=503, detail="Service unavailable")
        except Exception as e:
            logger.error(f"Request forwarding error: {e}", exc_info=True)
            raise HTTPException(status_code=502, detail="Bad gateway")
    
    async def _record_metrics(
        self, 
        request_id: str, 
        route_info: Optional[Dict[str, Any]], 
        duration: float, 
        success: bool
    ):
        """
        记录请求指标
        
        Args:
            request_id: 请求ID
            route_info: 路由信息
            duration: 请求持续时间
            success: 是否成功
        """
        if not self.cache_service:
            return
        
        # 记录基本指标
        metrics_key = "gateway:metrics"
        current_metrics = await self.cache_service.get(metrics_key) or {
            "total_requests": 0,
            "successful_requests": 0,
            "failed_requests": 0,
            "total_duration": 0.0,
            "avg_duration": 0.0
        }
        
        current_metrics["total_requests"] += 1
        current_metrics["total_duration"] += duration
        current_metrics["avg_duration"] = current_metrics["total_duration"] / current_metrics["total_requests"]
        
        if success:
            current_metrics["successful_requests"] += 1
        else:
            current_metrics["failed_requests"] += 1
        
        await self.cache_service.set(metrics_key, current_metrics, ttl=3600)  # 1小时缓存
    
    async def get_config_info(self) -> Dict[str, Any]:
        """
        获取配置信息
        
        Returns:
            Dict[str, Any]: 配置信息
        """
        return {
            "service_name": self.config.get("service_name", "api-gateway"),
            "version": self.config.get("service_version", "1.0.0"),
            "environment": self.config.get("environment", "development"),
            "routes_count": len(self.config.get("routes", [])),
            "services_count": len(self.config.get("services", {})),
            "features": {
                "rate_limiting": self.config.get("rate_limiting_enabled", True),
                "circuit_breaker": self.config.get("circuit_breaker_enabled", True),
                "caching": self.cache_service is not None,
                "events": self.event_bus is not None,
                "middleware": self.middleware_manager is not None
            }
        }
    
    async def close(self):
        """关闭服务"""
        if self.http_client:
            await self.http_client.aclose()
        logger.info("Gateway service closed")
